介绍nginx中location块的匹配符(~, ~*, ^~, [space]等)与alias文件代理的关系
实验环境
静态资源目录
E: /static
- a.js
- b.js
-
/case/
- c.js
- d.js
- e.js
nginx server块
server {
listen 80;
server_name 127.0.0.1;
}
alias代理特定文件
仅仅代理一个特定的文件,基本上很少会出错,
location块是前缀匹配和正则匹配均可。
如下,浏览器访问http://127.0.0.1/static/case/... 都返回c.js的内容。
location /static/case/c.js {
alias E:/static/case/c.js;
}
location ~ /static/case/c.js {
alias E:/static/case/c.js;
}
alias代理某目录下的各个文件
但当需要代理一个目录下的各个文件时,会因location块是前缀匹配和正则匹配的不同,导致代理的结果不同。
尤其是location是正则匹配时,较为特殊,容易出错。
location是前缀匹配^~或者[space]时
这种情况如果出错,一般就是由于对location URI部分和alias部分最后加不加“/”犯糊涂导致的,
或者说是不清楚这种情况下最终代理到什么path导致的。
// case1
location /static/case/ {
alias E:/static/case/;
autoindex on;
}
// case2
location /static/case {
alias E:/static/case/;
autoindex on;
}
case3
location /static/case/ {
alias E:/static/case;
autoindex on;
}
case4
location /static/case {
alias E:/static/case;
autoindex on;
}
以上四种情况,浏览器输入:http://127.0.0.1/static/case/... 只有第三种失败。
如果在这四种情况的location前面都加上 ^~ 结果也是一样的,因为 ^~ 和[space]都是前缀匹配。
**最终代理路径是: alias路径 + location部分URI和浏览器输入的URL未匹配到的部分。
这个路径下有文件,就200,没有文件,就404。**
所以分析一下为什么第三种写法不能正确代理呢,
浏览器URL: http://127.0.0.1/static/case/...,
location:/static/case/,
因此两个URL匹配部分是/static/case/,
未匹配部分是c.js。
因此它最终代理的path是:E:/static/case + c.js = E:/static/casec.js,相当于找static目录下有没有casec.js文件,因为没这个文件,所以404。
location是正则匹配~, ~*时
location ~ /static/case/ {
alias E:/static/case/;
autoindex on;
}
浏览器URL1:http://127.0.0.1/static/case/...
浏览器URL2:http://127.0.0.1/static/case/...
浏览器URL3:http://127.0.0.1/static/case/...
浏览器URL4:http://127.0.0.1/static/case/,
结果都是一样的,返回/static/case目录。
其中只有URL4,直接200返回。URL1-3都是301->200。
重定向不是无限的,当浏览器URL case后的层级大于10时,就不再301->200,而是直接200返回。
即,浏览器URL5,直接200返回。代理到/static/case目录。
浏览器URL5:http://127.0.0.1/static/case/...
因此,代理目录时,location还是正则匹配的话,是无法访问到这个目录下的各个文件的。
解决办法有两个。
关于既想用~又想能代理到某目录下各个文件的解决办法:
//方案1
location ~ ^/(.+)/(.+)/(.+\.js)$ {
alias E:/static/case/$3;
}
//方案2、用root结合rewrite代替
location ~ ^/.+/.+/.+\.js$ {
root E:/;
rewrite ^/(.*) /$1 break;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。